package zcatt.examples.swt.widgets;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;


import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseTrackAdapter;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Device;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Sash;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;

public class WidgetExample {
	static final int MARGIN = 5;
	static final int SASH_SPACING = 1;
	
	Display display;
	Shell shell;
	
	WidgetTab[] tabs;
	WidgetTab curTab;
	
	ToolBar toolBar;
	Tree tabTree;
	Sash vSash;
	Composite widgetComp;	//zf, 只允许一个child
	Group settingsPanel;
	
	List<Image> imgList;		//remember to dispose
	List<WidgetTab>  tabOrderList;
	
	public WidgetExample(Display display)
	{
		this.display = display;
		
		imgList = new ArrayList<Image>();
		tabs = null; 
		curTab = null;
	}
	
	public void open()
	{
		shell = new Shell(display);
		shell.setText("Widget Examples");
		shell.addDisposeListener(event-> dispose());
		
		WidgetTab defaultTab;
		tabs = new WidgetTab[] {
				new IntroTab(this),
				new LabelTab(this),
				new ButtonTab(this),				
				new CanvasTab(this),
				new CaretTab(this),
				new SpecialDialogsTab(this),
				new ModalDialogTab(this),
				new ComboTab(this),
				new CoolBarTab(this),
				new DateTimeTab(this),
				new ExpandBarTab(this),
				new LinkTab(this),
				new MenuTab(this),
				new ListTab(this),
				new MonitorTab(this),
				new ProgressBarTab(this),
				new SashTab(this),
				new ScaleTab(this),
				new SliderTab(this),
				new SpinnerTab(this),
				new TabFolderTab(this),
				new TableTab(this),
				new ToolBarTab(this),
				new TrayTab(this),
				new VirtualTableTab(this),
				new TreeTab(this),
				new TrackerTab(this),
				new BusyIndicatorTab(this),
				new CBannerTab(this),
				new CComboTab(this),
				new CLabelTab(this),
				new ControlEditorTab(this),
				new CTabFolderTab(this),
				new PopupListTab(this),
				new SashFormTab(this),
				new ScrolledCompositeTab(this),
				new StackLayoutTab(this),
				new ViewFormTab(this),
				new TableCursorTab(this),
				new TableEditorTab(this),
				new TreeCursorTab(this),
				new TreeEditorTab(this),
				new StyledTextTab(this),
		};
		defaultTab = tabs[tabs.length-1];
		
		Arrays.sort(tabs, (a,b)-> a.getText().compareTo(b.getText()));
		
		createContents();
		
		setTab(defaultTab);		
		
		shell.open();
	}
	
	public void dispose()
	{
		for(Image e: imgList)
			e.dispose();
		imgList = null;		
		
		if(tabs != null)
			for(WidgetTab e: tabs)
				e.dispose();
	
		tabs = null;		
	}
	
	void createContents()
	{
		
		//#. toolBar
		
		toolBar = new ToolBar(shell, SWT.NONE);
		
		ToolItem toolItem;
		
		toolItem = new ToolItem(toolBar, SWT.PUSH);
		toolItem.setText("Back");
		toolItem.setImage(loadImage("back.gif"));
		toolItem.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e)
			{
				int index = tabOrderList.indexOf(curTab) -1;
				if(index <0)
					index = tabOrderList.size() -1;
				setTab(tabOrderList.get(index));
			}
		});

		toolItem = new ToolItem(toolBar, SWT.PUSH);
		toolItem.setText("Next");
		toolItem.setImage(loadImage("next.gif"));
		toolItem.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e)
			{
				int index = tabOrderList.indexOf(curTab) +1;
				if(index >= tabOrderList.size())
					index = 0;
				setTab(tabOrderList.get(index));
			}
		});
		
		
		//#.tree
		tabTree = new Tree(shell, SWT.SINGLE|SWT.BORDER|SWT.H_SCROLL|SWT.V_SCROLL);
		tabTree.setToolTipText("show widgets");
		
		//##.collect categories and tabOrderList
		HashSet<String> set = new HashSet<>();
		for(WidgetTab e: tabs)
		{
			assert !e.getCategory().isEmpty();
			set.add(e.getCategory());
		}
		String[] categories = new String[set.size()];
		set.toArray(categories);
		Arrays.sort(categories);
		
		tabOrderList = new ArrayList<>();

		for(String e: categories)
		{
			TreeItem item = new TreeItem(tabTree, SWT.NONE);
			item.setText(e);
			for(WidgetTab t: tabs)
			{
				if(e.equals(t.getCategory()))
				{
					TreeItem item2 = new TreeItem(item, SWT.NONE);
					item2.setText(t.getText());
					item2.setData(t);
					tabOrderList.add(t);					
				}
			}
		}
		
		tabTree.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				TreeItem item = (TreeItem) e.item;
				if(item != null)
				{
					WidgetTab tab = (WidgetTab) item.getData();
					setTab(tab);
				}
				
			}
			
		});
		
		tabTree.addMouseTrackListener(new MouseTrackAdapter() {

			@Override
			public void mouseHover(MouseEvent event) {
				super.mouseHover(event);

				Point pt = new Point(event.x, event.y);
				String desc = null; 
				try {
					TreeItem item = tabTree.getItem(pt);
					WidgetTab tab = (WidgetTab) item.getData();
					desc = tab.getDescription();
				}
				catch(Exception e)
				{
				}
				tabTree.setToolTipText(desc);
			}
			
		});
		
		//#.vSash
		vSash = new Sash(shell, SWT.VERTICAL);
		vSash.addSelectionListener(SelectionListener.widgetSelectedAdapter(event->{
			Rectangle rect = shell.getClientArea();
			event.x = Math.min(Math.max(event.x, 50), rect.width - 50);
			if(event.detail != SWT.DRAG)
			{
				FormData data1 = (FormData)vSash.getLayoutData();
				data1.left.offset = event.x;
				vSash.requestLayout();				
			}
		}));
		
		//#.widgetComp
		GridLayout gridLayout;
		FillLayout fillLayout;
		widgetComp = new Composite(shell, SWT.BORDER);
		
		fillLayout = new FillLayout();
		widgetComp.setLayout(fillLayout);
		
		
		//#.settingsPanel
		settingsPanel = new Group(shell, SWT.SHADOW_ETCHED_IN);
		settingsPanel.setText("Settings");
		gridLayout = new GridLayout();
		settingsPanel.setLayout(gridLayout);
		
		//#.layout
		FormLayout formLayout = new FormLayout();
		shell.setLayout(formLayout);

		FormData data;
		
		data = new FormData();
		data.left = new FormAttachment(0, MARGIN);
		data.top = new FormAttachment(0, MARGIN);
		data.right = new FormAttachment(100, -MARGIN);
		toolBar.setLayoutData(data);

		data = new FormData();
		data.left = new FormAttachment(0, MARGIN);
		data.top = new FormAttachment(toolBar, MARGIN);
		data.right = new FormAttachment(vSash, -SASH_SPACING);
		data.bottom = new FormAttachment(100, -MARGIN);		
		tabTree.setLayoutData(data);
		
		data = new FormData();
		data.left = new FormAttachment(null, tabTree.computeSize(SWT.DEFAULT, SWT.DEFAULT).x+50);
		data.top = new FormAttachment(toolBar, MARGIN);
		data.bottom = new FormAttachment(100, -MARGIN);		
		vSash.setLayoutData(data);
		
		data = new FormData();
		data.left = new FormAttachment(vSash, SASH_SPACING);
		data.top = new FormAttachment(toolBar, MARGIN);
		data.bottom = new FormAttachment(settingsPanel);		
		data.right = new FormAttachment(100, -MARGIN);
		widgetComp.setLayoutData(data);

		data = new FormData();
		data.left = new FormAttachment(vSash, SASH_SPACING);
		data.bottom = new FormAttachment(100, -MARGIN);		
		data.right = new FormAttachment(100, -MARGIN);
		settingsPanel.setLayoutData(data);		
	}
	
	void setTab(WidgetTab tab)
	{
		if(curTab == tab)
			return;
		
		Control[] children;	
	
		children = settingsPanel.getChildren();
		for(Control e: children)
			e.dispose();
		
		curTab = tab;
		if(curTab != null)
		{
			TreeItem[] selection = tabTree.getSelection();
			if (selection.length == 0 || selection[0].getData() != curTab) {
				TreeItem item = findItemByData(tabTree.getItems(), curTab);
				if (item != null) tabTree.setSelection(new TreeItem[]{item});
			}

			curTab.createControlPanel(settingsPanel);			
			recreateWidgetComp();
		}
		
		FormData data = (FormData) settingsPanel.getLayoutData();
		children = settingsPanel.getChildren();
		if(children.length != 0)
		{
			data.top = null;			
		}
		else
		{
			data.top = new FormAttachment(100, -MARGIN);			
		}

		shell.layout(true, true);		
	}
	
	void recreateWidgetComp()
	{
		Control[] children;
		
		children = widgetComp.getChildren();
		assert children.length <= 1;
	
		for(Control e: children)
			e.dispose();
		
		curTab.createWidget(widgetComp);
		assert children.length <= 1;
		
		
		widgetComp.layout(true, true);	
	}	
	
	TreeItem findItemByData(TreeItem[] items, Object data) {
		for (TreeItem item : items) {
			if (item.getData() == data) return item;
			item = findItemByData(item.getItems(), data);
			if (item != null) return item;
		}
		return null;
	}
	
	public Image loadImage(String fileName)
	{
		Image image = loadImage(display, fileName);
		
		if(image!=null)
			imgList.add(image);
		
		return image;
	}
	
	public static Image loadImage(Device device, String fileName)
	{
		InputStream is = WidgetExample.class.getResourceAsStream(fileName);
		if(is == null)
			return null;
		Image image = null;
		try {
			image = new Image(device, is);
		}
		catch(Exception e)
		{}
		finally
		{
			try {
				is.close();
			}
			catch(Exception e)
			{}
		}
		
		return image;		
	}

	public static void main(String[] args) {
		Display display = new Display();
		WidgetExample example = new WidgetExample(display);
		example.open();
		while(example.shell != null && !example.shell.isDisposed())
		{
			if(!display.readAndDispatch())
				display.sleep();
		}
		display.dispose();
	}

}
